package com.example.lib_common.video

import android.content.Context
import android.graphics.Rect
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.analytics.AnalyticsListener
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.StyledPlayerView
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util


/**
 *@author yaotianxue
 *@description recyclerView中播放视频
 *@date 2022/10/20 9:18
 */
abstract class VideoRecyclerViewHelper {


    private var context: Context? = null

    private var recyclerView: RecyclerView? = null

    //视频相关
    private var videoSurfaceView: StyledPlayerView? = null
    private var videoPlayer: ExoPlayer? = null

    //视频容器
    private var mediaContainer: FrameLayout? = null

    //封面
    private var mediaCover: ImageView? = null
    private var parentViewHolder: View? = null

    //缓冲图标
    private var loadingView: View? = null

    //播放图标
    private var playView: View? = null

    private var isVideoViewAdded = false

    //当前播放的位置
    private var playPosition = -1

    //封面隐藏过渡
    private var alphaAniHide: AlphaAnimation? = null

    private var mFullScreen: Boolean = false
    private var autoPlay: Boolean = true

    private val TAG = "VideoRecyclerViewHelper"

    private var onPlayingVideoClick: ((StyledPlayerView, String) -> Unit)? = null
    private var onNotPlayingVideoClick: ((String) -> Unit)? = null
    private fun alphaAnimation() {
        alphaAniHide = AlphaAnimation(1f, 0f)
        alphaAniHide!!.duration = 300
    }


    private val hideAnimationListener = object : Animation.AnimationListener {
        override fun onAnimationStart(p0: Animation?) {
        }

        override fun onAnimationEnd(p0: Animation?) {
            mediaCover?.visibility = View.INVISIBLE
        }

        override fun onAnimationRepeat(p0: Animation?) {
        }
    }

    //初始化
    fun init(
        context: Context, recyclerView: RecyclerView,
        onPlayingVideoClick: ((StyledPlayerView, String) -> Unit)?,
        onNotPlayingVideoClick: ((videoUrl: String) -> Unit)?
    ) {
        alphaAnimation()
        this.context = context
        this.recyclerView = recyclerView
        this.onPlayingVideoClick = onPlayingVideoClick
        this.onNotPlayingVideoClick = onNotPlayingVideoClick
        videoSurfaceView = StyledPlayerView(context)
        videoSurfaceView!!.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
        videoPlayer = ExoPlayer.Builder(context).build()
        videoSurfaceView!!.player = videoPlayer

        //列表中隐藏控制器
        isShowVideoSurfaceViewController(false)
        //列表中静音
        isMute(true)

        //视频首帧渲染监听
        videoPlayer!!.addAnalyticsListener(object : AnalyticsListener {
            override fun onRenderedFirstFrame(eventTime: AnalyticsListener.EventTime, output: Any, renderTimeMs: Long) {
                super.onRenderedFirstFrame(eventTime, output, renderTimeMs)
                Log.d(TAG, "onRenderedFirstFrame")
                // if (mediaCover?.visibility == View.INVISIBLE) {
                //     return
                //  }
                mediaCover?.startAnimation(alphaAniHide)
                alphaAniHide?.setAnimationListener(hideAnimationListener)
            }
        })

        videoPlayer!!.addListener(object : Player.Listener {
            override fun onLoadingChanged(isLoading: Boolean) {
                Log.d(TAG, "onPlayerStateChanged onLoadingChanged - ${isVideoViewAdded}  ${isLoading}")
                if (!isLoading) {
                    loadingView?.visibility = View.GONE
                    playView?.visibility = View.GONE
                }
            }

            override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
                Log.d(TAG, "onPlayerStateChanged -${playbackState} - isVideoViewAdded:${isVideoViewAdded}")
                when (playbackState) {
                    Player.STATE_BUFFERING -> {
                        Log.d(TAG, "onPlayerStateChanged: Buffering video.")
                        if (!isVideoViewAdded) {
                            loadingView?.visibility = View.VISIBLE
                            playView?.visibility = View.GONE
                        }
                    }
                    Player.STATE_ENDED -> {
                        Log.d(TAG, "onPlayerStateChanged: Video ended.")
                        videoPlayer!!.seekTo(0)
                    }
                    Player.STATE_IDLE -> {}
                    Player.STATE_READY -> {
                        Log.d(TAG, "onPlayerStateChanged: Ready to play.")
                        if (!isVideoViewAdded) {
                            loadingView?.visibility = View.GONE
                            playView?.visibility = View.GONE
                            addVideoView()
                        }
                    }
                    else -> {}
                }
            }
        })

        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    if (autoPlay) {
                        if (recyclerView.canScrollVertically(1)) {
                            playVideo()
                        }
                    } else {
                        if (isVideoViewAdded) {
                            resetVideoView()
                        }
                    }
                }
            }

        })

        recyclerView.addOnChildAttachStateChangeListener(object : RecyclerView.OnChildAttachStateChangeListener {
            override fun onChildViewAttachedToWindow(view: View) {}
            override fun onChildViewDetachedFromWindow(view: View) {
                if (parentViewHolder != null && parentViewHolder == view) {
                    Log.d(TAG, "onChildViewDetachedFromWindow")
                    resetVideoView()
                }
            }
        })
    }


    // Remove the old player
    private fun removeVideoView(videoView: StyledPlayerView) {
        val parent = videoView.parent as? ViewGroup ?: return
        val index = parent.indexOfChild(videoView)
        if (index >= 0) {
            parent.removeViewAt(index)
            isVideoViewAdded = false
            //  mediaContainer?.setOnClickListener(null)
        }
    }

    private fun addVideoView() {
        if (videoSurfaceView?.parent as? ViewGroup != null) {
            (videoSurfaceView?.parent as? ViewGroup)!!.removeView(videoSurfaceView)
        }
        if (mediaContainer == null) return
        mediaContainer?.addView(videoSurfaceView, 0)
        isVideoViewAdded = true
        videoSurfaceView!!.requestFocus()
        videoSurfaceView!!.alpha = 1f
        videoSurfaceView!!.visibility = View.VISIBLE
    }

    private fun resetVideoView() {
        if (isVideoViewAdded) {
            removeVideoView(videoSurfaceView!!)
            playPosition = -1
            playView?.visibility = View.VISIBLE
            loadingView?.visibility = View.GONE
            videoSurfaceView?.visibility = View.INVISIBLE
            mediaCover?.visibility = View.VISIBLE
        }
    }


    fun playVideo() {
        if (recyclerView == null) {
            return
        }
        var targetPosition: Int = -1


        val startPosition = (recyclerView!!.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
        var endPosition = (recyclerView!!.layoutManager as LinearLayoutManager).findLastVisibleItemPosition()

        if (endPosition - startPosition > 1) {
            endPosition = startPosition + 1
        }

        if (startPosition < 0 || endPosition < 0) {
            return
        }

        if (startPosition != endPosition) {
            val startIsVideo = isVideo(startPosition)
            val endIsVideo = isVideo(endPosition)
            if (startIsVideo && !endIsVideo) {
                targetPosition = startPosition
            }

            if (!startIsVideo && endIsVideo) {
                targetPosition = endPosition
            }

            if (startIsVideo && endIsVideo) {
                val startPositionVideoHeightFloat: Float = getVisibleVideoSurfacePercent(startPosition)
                val endPositionVideoHeightFloat: Float = getVisibleVideoSurfacePercent(endPosition)
                targetPosition = if (startPositionVideoHeightFloat > endPositionVideoHeightFloat)
                    startPosition
                else
                    endPosition
            }
        } else {
            targetPosition = startPosition
        }

        Log.d(TAG, "playVideo: target position: $targetPosition")
        if (targetPosition == -1) {
            return
        }

        if (targetPosition == playPosition) {
            return
        }

        playPosition = targetPosition
        if (videoSurfaceView == null) {
            return
        }

        videoSurfaceView!!.visibility = View.INVISIBLE
        mediaCover?.visibility = View.VISIBLE
        playView?.visibility = View.VISIBLE
        removeVideoView(videoSurfaceView!!)
        val currentPosition = targetPosition - (recyclerView!!.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
        val child: View = recyclerView!!.getChildAt(currentPosition) ?: return

        val viewHolder: RecyclerView.ViewHolder? = recyclerView!!.getChildViewHolder(child)
        if (viewHolder == null) {
            playPosition = -1
            return
        }


        mediaContainer = getVideoContainer(viewHolder)
        mediaCover = getVideoCoverView(viewHolder)
        parentViewHolder = viewHolder.itemView
        loadingView = getVideoLoadingView(viewHolder)
        playView = getVideoIcon(viewHolder)
        videoSurfaceView!!.player = videoPlayer
        if (mediaContainer == null) {
            return
        }
        val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(
            context!!, Util.getUserAgent(context!!, "cyclone")
        )
        val mediaUrl: String? = getVideoUrl(targetPosition)
        if (mediaUrl != null) {
            if (onPlayingVideoClick != null) {
                videoSurfaceView!!.setOnClickListener {
                    if (!mFullScreen) {
                        if (targetPosition == playPosition) {
                            onEnterFullScreen(mediaUrl)
                        } else {
                            onNotPlayingVideoClick?.invoke(getVideoUrl(targetPosition) ?: "")
                        }
                    }
                }
            }

            Log.d(TAG, "playVideo: set video url : $mediaUrl")
            val proxyUrl: String = VideoCacheProxy.get()?.getProxyUrl(mediaUrl) ?: mediaUrl
            val videoSource: MediaSource = ProgressiveMediaSource.Factory(dataSourceFactory)
                .createMediaSource(MediaItem.fromUri(proxyUrl))
            videoPlayer!!.setMediaSource(videoSource)
            videoPlayer!!.prepare()
            videoPlayer!!.playWhenReady = true

        }
    }

    //进入全屏
    private fun onEnterFullScreen(videoUrl: String) {
        mFullScreen = true
        isMute(false)
        isShowVideoSurfaceViewController(true)
        videoSurfaceView!!.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
        mediaCover?.visibility = View.VISIBLE
        onPlayingVideoClick?.invoke(videoSurfaceView!!, videoUrl)
    }

    fun onExitFullScreen() {
        mFullScreen = false
        isMute(true)
        isShowVideoSurfaceViewController(false)
        videoSurfaceView!!.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
        mediaCover?.visibility = View.GONE
        addVideoView()
    }


    /**
     * Returns the visible region of the video surface on the screen.
     * if some is cut off, it will return less than the @videoSurfaceDefaultHeight
     */
    private fun getVisibleVideoSurfaceHeight(playPosition: Int): Int {
        if (recyclerView == null)
            return 0
        val at = playPosition - (recyclerView!!.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
        val child: View = recyclerView!!.getChildAt(at) ?: return 0
        //val location = IntArray(2)
        // child.getLocationInWindow(location)
        //        return if (location[1] < 0) {
//            location[1] + videoSurfaceDefaultHeight
//        } else {
//            screenDefaultHeight - location[1]
//        }
        val viewRect = Rect()
        child.getGlobalVisibleRect(viewRect)

        return viewRect.bottom - viewRect.top
    }

    //View显示百分比
    private fun getVisibleVideoSurfacePercent(playPosition: Int): Float {
        if (recyclerView == null)
            return 0f
        val at = playPosition - (recyclerView!!.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
        val child: View = recyclerView!!.getChildAt(at) ?: return 0f
        val viewRect = Rect()
        child.getGlobalVisibleRect(viewRect)
        return (viewRect.bottom - viewRect.top).toFloat() / child.height
    }


    //静音
    fun isMute(mute: Boolean) {
        videoPlayer?.volume = if (mute) 0f else 1f
    }

    //显示控制器
    fun isShowVideoSurfaceViewController(show: Boolean) {
        videoSurfaceView!!.useController = show
        if (show) {
            videoSurfaceView!!.setShowNextButton(false)
            videoSurfaceView!!.setShowPreviousButton(false)
            videoSurfaceView!!.setShowFastForwardButton(false)
            videoSurfaceView!!.setShowRewindButton(false)
            videoSurfaceView!!.setShowVrButton(false)
            videoSurfaceView!!.setShowShuffleButton(false)
            videoSurfaceView!!.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
            //设置按钮取消显示
            videoSurfaceView!!.findViewById<View>(com.google.android.exoplayer2.ui.R.id.exo_settings).visibility = View.GONE
        }
    }


    fun autoPlay(auto: Boolean) {
        this.autoPlay = auto
    }

    fun pausePlayer() {
        if (this.videoPlayer?.isPlaying == true && isVideoViewAdded) {
            this.videoPlayer?.pause()
        }
    }

    fun hidePlayerView() {
        if (isVideoViewAdded)
            videoSurfaceView?.visibility = View.INVISIBLE
    }

    fun startPlayer() {
        if (this.videoPlayer?.isPlaying != true && isVideoViewAdded) {
            videoSurfaceView?.visibility = View.VISIBLE
            this.videoPlayer?.play()
        }

    }

    fun releasePlayer() {
        if (videoPlayer != null) {
            videoPlayer!!.release()
            videoPlayer = null
        }
        parentViewHolder = null
    }


    //视频链接
    abstract fun getVideoUrl(position: Int): String?

    //视频容器
    abstract fun getVideoContainer(viewHolder: RecyclerView.ViewHolder): FrameLayout?

    //视频封面
    abstract fun getVideoCoverView(viewHolder: RecyclerView.ViewHolder): ImageView?

    //视频缓冲加载图标
    open fun getVideoLoadingView(viewHolder: RecyclerView.ViewHolder): View? {
        return null
    }

    //视频播放图标
    open fun getVideoIcon(viewHolder: RecyclerView.ViewHolder): View? {
        return null
    }

    //返回当前item是否为视频
    open fun isVideo(position: Int): Boolean {
        return true
    }


}